﻿using System;
using System.Management;
using System.ComponentModel;
using System.Runtime.InteropServices;

//Lists connected USB devices, simply lists the device as it is either connected
//or disconnected.
namespace Sensors
{
    class USBSensor
    {
        public void run()
        {
            try
            {
                ManagementObjectSearcher searcher =
                      new ManagementObjectSearcher("root\\CIMV2",
                      "SELECT * FROM Win32_USBControllerDevice");
                foreach (ManagementObject queryObj in searcher.Get())
                {
                    Console.WriteLine("-----------------------------------");
                    Console.WriteLine("Win32_USBControllerDevice instance");
                    Console.WriteLine("-----------------------------------");
                    Console.WriteLine("Antecedent: {0}", queryObj["Antecedent"]);
                    Console.WriteLine("Dependent: {0}", queryObj["Dependent"]);
                    Console.WriteLine("-------------Dependent-------------");
                    ManagementObject mbo = new ManagementObject(queryObj["Dependent"].ToString());
                    foreach (PropertyData prop in mbo.Properties)
                    {
                        if (prop.Value != null)
                            Console.WriteLine("{0}: {1}", prop.Name, prop.Value);
                    }
                    Console.WriteLine("-----------------------------------");
                }
            }
            catch (ManagementException e)
            {
                Console.WriteLine("An error occurred while querying for WMI data: " + e.Message);
            }

            USBSensor usbsense = new USBSensor();
            ManagementEventWatcher w = null;
            ManagementEventWatcher x = null;
            WqlEventQuery q;
            WqlEventQuery r;
            ManagementOperationObserver observer = new ManagementOperationObserver();

            ManagementScope scope = new ManagementScope("root\\CIMV2");

            scope.Options.EnablePrivileges = true;

            try
            {
                //USB DEVICE CONNECTION
                q = new WqlEventQuery();
                q.EventClassName = "__InstanceCreationEvent";
                q.WithinInterval = new TimeSpan(0, 0, 10);
                q.Condition = @"TargetInstance ISA 'Win32_USBControllerDevice'";
                Console.WriteLine(q.QueryString);

                //USB DEVICE DISCONNECTION
                r = new WqlEventQuery();
                r.EventClassName = "__InstanceDeletionEvent";
                r.WithinInterval = new TimeSpan(0, 0, 10);
                r.Condition = @"TargetInstance ISA 'Win32_USBControllerDevice'";
                Console.WriteLine(r.QueryString);

                //EventWatcher for Connections
                w = new ManagementEventWatcher(scope, q);
                w.EventArrived += new EventArrivedEventHandler(usbsense.USBEventArrived);
                w.Start();
                //EventWatcher for Disconnections
                x = new ManagementEventWatcher(scope, r);
                x.EventArrived += new EventArrivedEventHandler(usbsense.USBEventArrived);
                x.Start();

                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                w.Stop();
            }
        }

        public void USBEventArrived(object sender, EventArrivedEventArgs e)
        {
            foreach (PropertyData pd in e.NewEvent.Properties)
            {
                Console.WriteLine("\n=======");
                Console.WriteLine("{0},{1},{2},{3}", pd.Name, pd.Type, pd.Value, pd.Origin);

                ManagementBaseObject mbo = null;

                if ((mbo = pd.Value as ManagementBaseObject) != null)
                {
                    Console.WriteLine("---Properties");
                    foreach (PropertyData prop in mbo.Properties)
                        Console.WriteLine("{0} - {1}", prop.Name, prop.Value);
                }
            }
        }
    }
}
